package com.example.swimfish;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import lombok.extern.java.Log;

import java.net.URI;
import java.util.*;

public class MainApp extends Application {
    private Aquarium2DView aquarium;
    private WebSocketClient webSocketClient;
    private AudioManager audioManager;
    private WebSocketServer webSocketServer;
    private final Integer FISHQUANTITY = 2;
    private List<String> peerHosts = new ArrayList<>();
    private Map<String, AnimatedFishModel> activeFishes = new HashMap<>();
    private String localHostId = UUID.randomUUID().toString();
    private String localIP;
    private Timer networkDiscoveryTimer;
    private PeerDiscoveryServer discoveryServer;

    @Override
    public void start(Stage primaryStage) {
        // 启动UDP响应服务
        discoveryServer = new PeerDiscoveryServer();
        discoveryServer.start();
        // 获取本地IP地址
        localIP = NetworkUtils.getLocalIP();
        System.out.println("本机IP地址: " + localIP);

        List<String> peers = NetworkUtils.discoverPeersUsingUDP();
        System.out.println("发现的网络主机: " + peers);


        // 初始化WebSocket服务器
        webSocketServer = new WebSocketServer();
        webSocketServer.start();

        // 初始化网络发现
        setupNetworkDiscovery();

        // 初始化WebSocket客户端
        try {
            webSocketClient = new WebSocketClient(
                    new URI("ws://localhost:8025/ws/fish"),
                    this::handleIncomingFish
            );
            webSocketClient.connect();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 模拟添加几个已知主机
        peerHosts.add("192.168.1.2");
        peerHosts.add("192.168.1.3");

        // 初始化水族箱
        aquarium = new Aquarium2DView();

        // 加载鱼动画精灵图
        Image fishSpriteSheet = new Image(getClass().getResourceAsStream("/image/fish8.png"));


        // 添加初始鱼群
        for (int i = 0; i < FISHQUANTITY; i++) {
            addLocalFish(fishSpriteSheet);
        }

        Scene scene = new Scene(aquarium);
        primaryStage.setTitle("分布式水族箱 - 主机: " + localHostId.substring(0, 8));
        primaryStage.setScene(scene);
        primaryStage.show();

        // 动画循环
        new AnimationTimer() {
            @Override
            public void handle(long now) {
                updateFishPositions();
                checkFishBoundaries();
            }
        }.start();

        // 初始化音频
        audioManager = new AudioManager();
        audioManager.playBackground();
    }
    //网络发现
    private void setupNetworkDiscovery() {
        // 初始扫描
        scanNetworkPeers();

        // 设置定时扫描
        networkDiscoveryTimer = new Timer(true);
        networkDiscoveryTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                scanNetworkPeers();
            }
        }, 0, 30000); // 每30秒扫描一次
    }
    private void scanNetworkPeers() {
        // 扫描局域网中的其他主机 (例如扫描192.168.1.1到192.168.1.254)
        List<String> discoveredPeers = NetworkUtils.discoverPeersUsingUDP();
//        List<String> discoveredPeers =peerHosts;
        // 过滤掉本机IP
        discoveredPeers.remove(localIP);

        // 更新peerHosts列表
        synchronized (peerHosts) {
            peerHosts.clear();
            peerHosts.addAll(discoveredPeers);
        }

        System.out.println("发现网络中的主机: " + discoveredPeers);
    }


    private void addLocalFish(Image fishSpriteSheet) {
        AnimatedFishModel fish = new AnimatedFishModel(fishSpriteSheet);
        fish.setTranslateX(Math.random() * aquarium.getWidth());
        fish.setTranslateY(Math.random() * aquarium.getHeight());
        aquarium.addFish(fish);
        activeFishes.put(fish.getFishId(), fish);
    }

    private void updateFishPositions() {
        Group fishesGroup = (Group) aquarium.getChildren().get(1);
        fishesGroup.getChildren().forEach(node -> {
            if (node instanceof AnimatedFishModel) {
                ((AnimatedFishModel) node).updatePosition();
            }
        });
    }

    private void checkFishBoundaries() {
        List<AnimatedFishModel> fishesToRemove = new ArrayList<>();

        activeFishes.values().forEach(fish -> {
            double x = fish.getTranslateX();
            double y = fish.getTranslateY();
            double width = fish.getBoundsInParent().getWidth();
            double height = fish.getBoundsInParent().getHeight();

            // 增强边界检测
            boolean outLeft = x + width < 0;
            boolean outRight = x > aquarium.getWidth();
            boolean outTop = y + height < 0;
            boolean outBottom = y > aquarium.getHeight();

            if (outLeft || outRight || outTop || outBottom) {
                System.out.printf("鱼 %s 游出边界: x=%.1f, y=%.1f, 方向(%.2f,%.2f)%n",
                    fish.getFishId(), x, y, fish.getDirectionX(), fish.getDirectionY());

                fishesToRemove.add(fish);
                sendFishToOtherHost(fish);
            }
        });

        // 移除已发送到其他主机的鱼
        fishesToRemove.forEach(fish -> {
            aquarium.removeFish(fish);
            activeFishes.remove(fish.getFishId());
            System.out.println("已移除鱼: " + fish.getFishId());
        });
    }

    private String determineExitDirection(double x, double y, double width, double height) {
        if (x + width < 0) return "left";
        if (x > aquarium.getWidth()) return "right";
        if (y + height < 0) return "top";
        if (y > aquarium.getHeight()) return "bottom";
        return "unknown";
    }

    private void sendFishToOtherHost(AnimatedFishModel fish) {
        if (!peerHosts.isEmpty()) {
            // 根据离开方向选择目标主机         // 简单实现: 随机选择一个主机
            String targetHost = selectTargetHost(fish.getDirectionX(), fish.getDirectionY());

            if (targetHost != null) {
                // 创建鱼的数据传输对象
                FishData fishData = new FishData(
                        fish.getTranslateX(),
                        fish.getTranslateY(),
                        fish.getDirectionX(),
                        fish.getDirectionY(),
                        localIP
                );

                // 发送到目标主机
                try {
                    webSocketClient.sendMessage(targetHost + "|" + fishData);
                    System.out.println("已发送鱼 " + fish.getFishId() + " 到主机 " + targetHost);
                } catch (Exception e) {
                    System.err.println("发送鱼到主机失败: " + e.getMessage());
                    // 发送失败则保留鱼
                    activeFishes.put(fish.getFishId(), fish);
                    aquarium.addFish(fish);
                }
            }else{
                System.out.println("没有其他主机");
            }
        }
    }
    private String selectTargetHost(double dirX, double dirY) {
        if (peerHosts.isEmpty()) {
            System.out.println("没有可用的对等主机");
            return null;
        }

        // 根据方向选择主机
        // 获取网络布局信息 (假设网络中的主机按顺序排列)
        synchronized (peerHosts) {
            if (Math.abs(dirX) > Math.abs(dirY)) {
                // 水平方向优先
                if (dirX > 0) {
                    // 向右游 - 选择列表中的下一个主机
                    int currentIndex = peerHosts.indexOf(localIP);
                    int nextIndex = (currentIndex + 1) % peerHosts.size();
                    return peerHosts.get(nextIndex);
                } else {
                    // 向左游 - 选择列表中的上一个主机
                    int currentIndex = peerHosts.indexOf(localIP);
                    int prevIndex = (currentIndex - 1 + peerHosts.size()) % peerHosts.size();
                    return peerHosts.get(prevIndex);
                }
            } else {
                // 垂直方向优先 (简化处理，选择随机主机)
                return peerHosts.get(new Random().nextInt(peerHosts.size()));
            }
        }
    }
//    private String selectTargetHost(double dirX, double dirY) {
//        // 根据方向选择主机
//        // 这里简化实现，实际应该根据主机布局映射
//
//        // 优先考虑水平方向
//        if (Math.abs(dirX) > Math.abs(dirY)) {
//            return dirX > 0 ? findRightHost() : findLeftHost();
//        } else {
//            return dirY > 0 ? findBottomHost() : findTopHost();
//        }
//
//    }
    // 示例方法 - 实际应该根据主机布局实现  selectTargetHost-主机发现
    private String findLeftHost() {
        return peerHosts.stream().findFirst().orElse(null);
    }
    private String findRightHost() {
        return peerHosts.stream().skip(1).findFirst().orElse(null);
    }
    private String findTopHost() {
        return peerHosts.stream().skip(2).findFirst().orElse(null);
    }
    private String findBottomHost() {
        return peerHosts.stream().skip(3).findFirst().orElse(null);
    }


    private void handleIncomingFish(String message) {
        // 解析消息格式: "host|fishData"
        String[] parts = message.split("\\|");
        if (parts.length == 2) {
            FishData fishData = FishData.fromString(parts[1]);
            //防止重复接受鱼
//            if (!activeFishes.containsKey(fishData.getFishId())) {
//            } else {
//                System.out.println("忽略重复鱼: " + fishData.getFishId());
//            }

            // 检查是否来自 已知主机
            if (!peerHosts.contains(fishData.getFromHost())) {
                System.out.println("收到来自未知主机的鱼: " + fishData.getFromHost());
                return;
            }

            javafx.application.Platform.runLater(() -> {
                // 在新主机上创建鱼
                Image fishSpriteSheet = new Image(getClass().getResourceAsStream("/image/fish8.png"));
                AnimatedFishModel fish = new AnimatedFishModel(fishSpriteSheet);

                // 设置鱼的位置和方向
                fish.setTranslateX(fishData.getX());
                fish.setTranslateY(fishData.getY());
                fish.setDirection(fishData.getDirX(), fishData.getDirY());

                // 根据方向设置进入位置
                setEntryPositionByDirection(fish, fishData.getDirX(), fishData.getDirY());

                aquarium.addFish(fish);
                activeFishes.put(fish.getFishId(), fish);
            });
        }
    }

    private void setEntryPositionByDirection(AnimatedFishModel fish, double dirX, double dirY) {
        double width = fish.getBoundsInParent().getWidth();
        double height = fish.getBoundsInParent().getHeight();

        // 优先考虑水平方向
        if (Math.abs(dirX) > Math.abs(dirY)) {
            if (dirX > 0) {
                // 从左边进入
                fish.setTranslateX(-width);
                fish.setTranslateY(Math.random() * aquarium.getHeight());
            } else {
                // 从右边进入
                fish.setTranslateX(aquarium.getWidth());
                fish.setTranslateY(Math.random() * aquarium.getHeight());
            }
        } else {
            if (dirY > 0) {
                // 从顶部进入
                fish.setTranslateX(Math.random() * aquarium.getWidth());
                fish.setTranslateY(-height);
            } else {
                // 从底部进入
                fish.setTranslateX(Math.random() * aquarium.getWidth());
                fish.setTranslateY(aquarium.getHeight());
            }
        }
    }
    private void adjustFishPositionForNewHost(AnimatedFishModel fish) {
        // 简单实现: 重置到随机位置

        // 实际应用中可以根据来源主机调整位置
        fish.setTranslateX(Math.random() * aquarium.getWidth());
        fish.setTranslateY(Math.random() * aquarium.getHeight());
    }

    @Override
    public void stop() {
        if (webSocketServer != null) {
            webSocketServer.stop();
        }
        if (audioManager != null) {
            audioManager.stopAll();
        }
        // 停止网络发现定时器
        if (networkDiscoveryTimer != null) {
            networkDiscoveryTimer.cancel();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}